//package com.gupaoedu.springframework.mvcframework.v2;
//
//import com.gupaoedu.springframework.mvcframework.annotation.MyAutowired;
//import com.gupaoedu.springframework.mvcframework.annotation.MyController;
//import com.gupaoedu.springframework.mvcframework.annotation.MyRequestMapping;
//import com.gupaoedu.springframework.mvcframework.annotation.MyService;
//
//import javax.servlet.ServletConfig;
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServlet;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.File;
//import java.io.IOException;
//import java.io.InputStream;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.net.URL;
//import java.util.*;
//
///**
// * projectName: my-springframwork
// * packageName: com.gupaoedu.springframework.mvcframework.v2
// * Created: 2019/3/25.
// * Auther: baifc
// * Description:
// */
//public class MyDispatcherServlet extends HttpServlet {
//
//    private Properties contextConfig = new Properties();
//
//    private List<String> classNameList = new ArrayList<>();
//
//    private Map<String, Object> ioc = new HashMap<>();
//
//    private Map<String, Method> handlerMapping = new HashMap<>();
//
//    @Override
//    public void init(ServletConfig config) throws ServletException  {
//
//        //1、加载配置文件
//        doLoadConfig(config.getInitParameter("contextConfigLocation"));
//
//        //2、扫描相关的类
//        doScanner(contextConfig.getProperty("scanPackage"));
//
//        //3、初始化所有相关的类的实例，并且放入到IOC 容器之中
//        doInstance();
//
//        //4、完成依赖注入
//        doAutoWried();
//
//        //5、初始化HandlerMapping
//        initHandlerMapping();
//
//        System.out.println("My Spring framework is init.");
//
//    }
//
//    @Override
//    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        this.doPost(request, response);
//    }
//
//    @Override
//    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        try {
//            this.doDispatch(request, response);
//        } catch (Exception e) {
//            e.printStackTrace();
//            response.getWriter().write("500 Exection,Detail : " + Arrays.toString(e.getStackTrace()));
//        }
//    }
//
//    private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//        String uri = request.getRequestURI();
//        System.out.println("uri = " + uri);
//        String contextPath = request.getContextPath();
//        System.out.println("contextPath = " + contextPath);
//
//        String url = uri.replace(contextPath, "");
//
//        if (!handlerMapping.containsKey(url)) {
//            response.getWriter().write("404 Not found");
//            return;
//        }
//
//        Method method = handlerMapping.get(url);
//
//        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());
//        System.out.println("beanName = " + beanName);
//
//        String name = request.getParameter("name");
//
//        method.invoke(ioc.get(beanName), new Object [] {request, response, name});
//    }
//
//
//    private void doLoadConfig(String contextConfigLocation) {
//
//        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
//
//        try {
//            contextConfig.load(is);
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            if (is != null) {
//                try {
//                    is.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//    }
//
//    private void doScanner(String packageName) {
//
//        String packagePath = "/" + packageName.replace(".", "/");
//
//        System.out.println("packagePath = " + packagePath);
//
//        URL url = this.getClass().getClassLoader().getResource(packagePath.replaceAll("/+", "/"));
//
//        File classPath = new File(url.getFile());
//
//        for (File file : classPath.listFiles()) {
//            if (file.isDirectory()) {
//                doScanner(packageName + "." + file.getName());
//            } else if (file.isFile() && file.getName().endsWith(".class")) {
//                classNameList.add(packageName + "." + file.getName().replace(".class", ""));
//            } else { continue; }
//
//        }
//    }
//
//
//    private void doInstance() {
//
//        if (classNameList.isEmpty()) {
//            return;
//        }
//        try {
//            for (String classPath : classNameList) {
//                System.out.println("className = " + classPath);
//                Class<?> clazz = Class.forName(classPath);
//                if (clazz.isAnnotationPresent(MyController.class)) {
//                    System.out.println("clazz.getName() = " + clazz.getName());
//                    String beanName = toLowerFirstCase(clazz.getSimpleName());
//                    ioc.put(beanName, clazz.newInstance());
//                } else if (clazz.isAnnotationPresent(MyService.class)) {
//
//                    MyService myService = clazz.getAnnotation(MyService.class);
//
//                    String beanName = myService.value();
//
//                    if ("".equals(beanName)) {
//                        beanName = toLowerFirstCase(clazz.getSimpleName());
//                    }
//
//                    Object instance = clazz.newInstance();
//
//                    ioc.put(beanName, instance);
//
//                    for (Class<?> inter : clazz.getInterfaces()) {
//                        if (ioc.containsKey(inter.getName())) {
//                            throw new Exception("bean " + inter.getSimpleName() + "is already exist！");
//                        }
//                        ioc.put(toLowerFirstCase(inter.getSimpleName()), instance);
//                    }
//                }
//
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    private void doAutoWried() {
//        if (ioc.isEmpty()) {
//            return;
//        }
//
//        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
//            Field[] fields = entry.getValue().getClass().getDeclaredFields();
//
//            for (Field field : fields) {
//                if (!field.isAnnotationPresent(MyAutowired.class)) {
//                    continue;
//                }
//                MyAutowired autowried = field.getAnnotation(MyAutowired.class);
//
//                String beanName = autowried.value();
//
//                if ("".equals(beanName)) {
//                    beanName = field.getName();
//                    System.out.println("field.getName() = " + field.getName());
//                    System.out.println("field.getType().getName() = " + field.getType().getName());
//                }
//
//                field.setAccessible(true);
//
//                try {
//                    field.set(entry.getValue(), ioc.get(beanName));
//                } catch (IllegalAccessException e) {
//                    e.printStackTrace();
//                }
//            }
//
//        }
//    }
//
//    private void initHandlerMapping() {
//        if (ioc.isEmpty()) {
//            return;
//        }
//
//        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
//            Class<?> clazz = entry.getValue().getClass();
//
//            if (!clazz.isAnnotationPresent(MyController.class)) {
//                continue;
//            }
//
//            String baseUrl = "";
//
//            if (clazz.isAnnotationPresent(MyRequestMapping.class)) {
//                baseUrl = clazz.getAnnotation(MyRequestMapping.class).value();
//            }
//
//            for (Method method : clazz.getMethods()) {
//                if (!method.isAnnotationPresent(MyRequestMapping.class)) {
//                    continue;
//                }
//
//                String methodUrl = method.getAnnotation(MyRequestMapping.class).value();
//
//                String url = ("/" + baseUrl + methodUrl).replaceAll("/+", "/");
//
//                handlerMapping.put(url, method);
//
//                System.out.println("Mapped :" + url + "," + method);
//            }
//        }
//    }
//
//
//    private String toLowerFirstCase(String className) {
//
//        char [] chars = className.toCharArray();
//
//        chars[0] += 32;
//
//        return String.valueOf(chars);
//
//    }
//
//
//}
